#ifndef AVALON_SIZEDECLARATIVEREADER_HPP
#define AVALON_SIZEDECLARATIVEREADER_HPP
#include <boost/cstdint.hpp>
#include "Avalon/Base/Handle.hpp"
#include "Avalon/IO/Reader.hpp"

namespace Avalon {
namespace IO {

  /*! \class SizeDeclariveReader
   *  \brief Reads data whose size is declared at the beginning.
   *  \author Kamal Mansouri <kranar@hotmail.com>
   */
  class SizeDeclarativeReader : public Reader {
    public:

      //! Constructs a SizeDeclarativeReader.
      /*!
        \param source The source to read from.
      */
      SizeDeclarativeReader(Carry<Reader> source);

      virtual ~SizeDeclarativeReader();

      virtual bool IsAtEndOfDataSource();

      virtual Threading::Async<int>::Ptr Read(void* destination, int size);

      virtual Threading::Async<int>::Ptr Read(Buffer* destination, int size);

      using Reader::Read;

    private:
      boost::recursive_mutex m_mutex;
      Handle<Reader> m_source;
      boost::uint32_t m_sizeRemaining;
      char* m_sizeReadIterator;
      Threading::Async<int>::Ptr m_sourceRead;

      void OnSizeRead(Buffer* buffer, void* destination, int size,
        const Threading::AsyncOwner<int>::Ptr& parsedRead,
        const Threading::Async<int>::Ptr& sourceRead);
      void OnDataRead(void* destination, boost::uint32_t totalSize,
        boost::uint32_t sizeToRead,
        const Threading::AsyncOwner<int>::Ptr& parsedRead,
        const Threading::Async<int>::Ptr& sourceRead);
  };
}
}

#endif // AVALON_SIZEDECLARATIVEREADER_HPP
